package com.example.learndemo.dataAlgorithm;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;

public class ArrayListTest<E> implements List<E> {
	private static final Object[] EMPTY_ARRAY = {};
	private int size;
	private int modCount=0;
	transient private Object[] data;

	public ArrayListTest() {
		this.size = 0;
		this.data = EMPTY_ARRAY;
	}

	@Override
	public int size() {
		return this.size;
	}

	@Override
	public boolean isEmpty() {
		return this.size == 0;
	}

	@Override
	public boolean contains(Object o) {
		if (o == null) {
			for (int i = 0; i < size; i++) {
				if (data[i] == null) {
					return true;
				}
			}
		} else {
			for (int i = 0; i < size; i++) {
				if (o.equals(data[i])) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public Iterator iterator() {
		return new Itr();
	}

	@Override
	public E[] toArray() {
		Object[] arr = new Object[size];
		System.arraycopy(data, 0, arr, 0, size - 1);
		return (E[]) arr;
	}

	@Override
	public boolean add(E e) {
		checkExpansion();
		data[size++] = e;
		return true;
	}

	private void checkExpansion() {
		if (this.size >= data.length) {
			Object[] newData = new Object[(data.length + 1) << 1];
			for (int i = 0; i < data.length; i++) {
				newData[i] = data[i];
			}
			data = newData;
		}
		modCount++;
	}

	private void checkExpansion(int needSize) {
		if (needSize > data.length) {
			Object[] newData = new Object[needSize];
			for (int i = 0; i < data.length; i++) {
				newData[i] = data[i];
			}
			data = newData;
		}
	}

	@Override
	public boolean remove(Object o) {
		if (o == null) {
			for (int i = 0; i < size; i++) {
				if (o == data[i]) {
					removeItem(i);
					return true;
				}
			}
		} else {
			for (int i = 0; i < size; i++) {
				if (o.equals(data[i])) {
					removeItem(i);
					return true;
				}
			}
		}
		return false;
	}

	private void removeItem(int i) {
		System.arraycopy(data, i + 1, data, i, size - i - 1);
		data[--size] = null;
	}



	@Override
	public boolean addAll(Collection c) {
		Object[] objects = c.toArray();
		int length = objects.length;
		checkExpansion(size + length);
		System.arraycopy(data, size, objects, 0, length - 1);
		size = +length;
		return true;
	}

	@Override
	public boolean addAll(int index, Collection c) {
		Object[] objects = c.toArray();
		int length = objects.length;
		checkRange(index);
		checkExpansion(size + length);
		System.arraycopy(data, index, data, index + length, length);
		System.arraycopy(objects, 0, data, index, length);
		size = +length;
		return true;
	}

	@Override
	public void clear() {
		size = 0;
		data = EMPTY_ARRAY;
	}

	@Override
	public E get(int index) {
		checkRange(index);
		return (E) data[index];
	}

	private void checkRange(int index) {
		if (index >= size || index < 0) {
			throw new ArrayIndexOutOfBoundsException();
		}
	}

	@Override
	public E set(int index, E element) {
		checkRange(index);
		Object oldItem = data[index];
		data[index] = element;
		return (E) oldItem;
	}

	@Override
	public void add(int index, E element) {
		checkRange(index);
		checkExpansion();
		System.arraycopy(data, index, data, index + 1, size - index + 1);
		data[index] = element;
		size++;
	}

	@Override
	public E remove(int index) {
		checkRange(index);
		Object oldItem = data[index];
		removeItem(index);
		return (E) oldItem;
	}

	@Override
	public int indexOf(Object o) {
		if (o == null) {
			for (int i = 0; i < size; i++) {
				if (data[i] == null) {
					return i;
				}
			}
		} else {
			for (int i = 0; i < size; i++) {
				if (o.equals(data[i])) {
					return i;
				}
			}
		}
		return -1;
	}

	@Override
	public int lastIndexOf(Object o) {
		if (o == null) {
			for (int i = size - 1; i >= 0; i--) {
				if (data[i] == null) {
					return i;
				}
			}
		} else {
			for (int i = size - 1; i >= 0; i--) {
				if (o.equals(data[i])) {
					return i;
				}
			}
		}
		return -1;
	}

	@Override
	public ListIterator listIterator() {
		// todo
		return null;
	}

	@Override
	public ListIterator listIterator(int index) {
		// todo
		return null;
	}

	@Override
	public List subList(int fromIndex, int toIndex) {
		return null;
	}

	@Override
	public boolean retainAll(Collection c) {
		return false;
	}

	@Override
	public boolean removeAll(Collection c) {
		return false;
	}

	@Override
	public boolean containsAll(Collection c) {
		return false;
	}

	@Override
	public Object[] toArray(Object[] a) {
		return new Object[0];
	}

	public String toString() {
		String str = "[";
		for (int i = 0; i < size; i++) {
			str += data[i];
			if (i < size - 1) {
				str += ",";
			}
		}
		str += "]";
		return str;
	}

	private class Itr implements Iterator<E> {
		private int index;

		public Itr() {
			this.index = 0;
		}

		@Override
		public boolean hasNext() {
			return this.index < size - 1;
		}

		@Override
		public E next() {
			checkRange(index);
			return (E) data[index++];
		}

		@Override
		public void remove() {

		}

		@Override
		public void forEachRemaining(Consumer<? super E> action) {

		}
	}

	public static void main(String[] args) {
		for (int i = 0; i <100 ; i++) {
			System.out.println("i = " + i);
			int []a=new int[Integer.MAX_VALUE>>4];
		}

		System.out.println("-----------");
	}
}
